package com.itheima.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.common.constant.RedisConstant;
import com.itheima.common.entity.PageResult;
import com.itheima.common.entity.QueryPageBean;
import com.itheima.mapper.CheckGroupMapper;
import com.itheima.mapper.SetmealCheckgroupMapper;
import com.itheima.mapper.SetmealMapper;
import com.itheima.pojo.CheckGroup;
import com.itheima.pojo.Setmeal;
import com.itheima.service.RedisService;
import com.itheima.service.SetmealService;
import freemarker.core.ParseException;
import freemarker.template.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfig;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.itheima.common.constant.RedisConstant.SETMEAL_PIC_DB_RESOURCES;


@Service
public class SetmealServiceImpl implements SetmealService {

    @Autowired
    private SetmealMapper setmealMapper;
    @Autowired
    private SetmealCheckgroupMapper setmealCheckgroupMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private RedisService redisService;

    @Autowired
    private CheckGroupMapper checkGroupMapper;

    @Value("${freemarker.out.path}")
    private String outputPath;

    @Autowired
    private Configuration freeMarkerConfig;
    private static final Pattern IMAGE_NAME_PATTERN = Pattern.compile("/([^/]+\\.(jpg|jpeg|png|gif|bmp))");

    /**
     * 新增体检套餐
     * @param setmeal
     */
    @Transactional
    @Override
    public void add(Setmeal setmeal,Integer[] checkGroupIds) {

        //新增体检套餐
        setmealMapper.add(setmeal);

        //获取体检套餐id，用于关联检查组
        Integer setmealId = setmeal.getId();

        //提取套餐中的图片URL并保存到Redis
        extractAndSaveImageNames(setmeal.getRemark());
        extractAndSaveImageNames(setmeal.getAttention());
        extractAndSaveImageNames(setmeal.getImg());

        List<CheckGroup> checkGroupList = new ArrayList<>();


        //判断关联表中的checkgroupId是否存在
        if(checkGroupIds != null && checkGroupIds.length>0){
            //如果存在，则往关联表中添加数据，遍历出checkgroupId
            for (Integer checkGroupId : checkGroupIds) {
                //写一个map集合存放数据
                Map<String, Integer> map = new HashMap<>();
                map.put("setmealId",setmealId);
                map.put("checkgroupId",checkGroupId);
                setmealMapper.insertCheckGroupAndSetmeal(map);
                checkGroupList.add(checkGroupMapper.findById(checkGroupId));
            }
        }
        //如果套餐有图片，将图片名称添加到Redis数据库集合
        if (setmeal.getImg() != null) {
            //从URL中提取文件名
            String fileName = setmeal.getImg().substring(setmeal.getImg().lastIndexOf("/") + 1);
            redisService.addPicToDbResources(fileName);
        }
        Map<String,Object> dataMap = new HashMap<>();
        dataMap.put("setmeal",setmeal);


        //查询对应的 checkGroupLis
        setmeal.setCheckGroups(checkGroupList);
        generateHtml("mobile_setmeal_detail.ftl",outputPath + "/" + setmeal.getId() + "page.html"  ,dataMap);

    }


    public void generateHtml(String templateName,String outputTemplateName,Map<String, Object> dataMap){
        try {
            //输出文件路径名称 outputTemplateName
            //templateName： templates下的模板名称
            FileOutputStream fileOutputStream = new FileOutputStream(outputTemplateName);
            Writer writer = new BufferedWriter(new OutputStreamWriter(fileOutputStream));
            Template template = freeMarkerConfig.getTemplate(templateName);
            //写入模板   null会报错
            template.process(dataMap, writer);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }




//下面与freemark无关
    private void extractAndSaveImageNames(String content) {
        if (content == null || content.isEmpty()) return;

        Matcher matcher = IMAGE_NAME_PATTERN.matcher(content);
        while (matcher.find()) {
            String imageName = matcher.group(1);
            redisTemplate.opsForSet().add(SETMEAL_PIC_DB_RESOURCES, imageName);
        }



    }

    /**
     * 体检套餐分页查询
     * @param queryPageBean
     * @return
     */
    @Override
    public PageResult findPage(QueryPageBean queryPageBean) {
        PageHelper.startPage(queryPageBean.getCurrentPage(),queryPageBean.getPageSize());
        Page<Setmeal> page = setmealMapper.findPage(queryPageBean);
        return new PageResult(page.getTotal(),page.getResult());
    }

    /**
     * 根据id查询体检信息
     * @param id
     * @return
     */
    @Override
    public Setmeal findById(Integer id) {
       Setmeal setmeal = setmealMapper.findById(id);
       return setmeal;
    }

    /**
     * 根据套餐id查询检查组id有多少
     * @param id
     * @return
     */
    @Override
    public List<Integer> findCheckgroupIdsBySetmealId(Integer id) {
        List<Integer> findCheckgroupIdsBySetmealId = setmealCheckgroupMapper.findCheckgroupIdsBySetmealId(id);
        return findCheckgroupIdsBySetmealId;
    }

    /**
     * 编辑体检套餐
     * @param setmeal
     * @param checkgroupIds
     */
    @Override
    public void edit(Setmeal setmeal, Integer[] checkgroupIds) {
        //修改检查组基本信息，操作检查组
        setmealMapper.edit(setmeal);
        //清理当前检查组关联的检查项
        setmealMapper.deleteAssociation(setmeal.getId());
        //重新建立当前检查组和检查项的关系
        //获取检查组id，用于后续关联关系插入
        Integer setmealId = setmeal.getId();

        //往检查项里添加东西（编码、名称、说明）
        //添加检查组与检查项的关联关系
        if (checkgroupIds != null && checkgroupIds.length > 0) {
            for (Integer checkGroupId : checkgroupIds) {//遍历检查项id数组
                Map<String,Integer> map = new HashMap<>();
                map.put("setmealId",setmealId);
                map.put("checkgroupId",checkGroupId);
                setmealMapper.insertCheckGroupAndSetmeal(map);
            }
        }
    }

    /**
     * 查询套餐数量
     * @return
     */
    public List<Map<String, Object>> findSetmealCount() {
        return setmealMapper.findSetmealCount();
    }
}
